package com.acme.chat.server;


import static com.acme.chat.settings.Settings.LOCALE_BUNDLE;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.apache.log4j.Logger;

/**
 * Class used to create new thread on each connected ChatClient.
 */
public class TCPServer implements Runnable {

    private static final String ERROR_SERVER_SOCKET_CREATION = LOCALE_BUNDLE.getString("ErrServerSocketCreation");
    private static final String ERROR_CANT_ACCEPT_CONNECTON = LOCALE_BUNDLE.getString("ErrCantAcceptConnection");
    private static final String ERROR_CLOSING_SERVER = LOCALE_BUNDLE.getString("ErrClosingServer");
    private static final String MESSAGE_SHUTDOWN_SERVER = "Shutdown server!";

    private static final int DEFAULT_PORT = 6800;

    private static Logger tcpLogger = Logger.getLogger(TCPServer.class.getName());

    private volatile boolean keepGoing;

    private int port;
    private ServerSocket serverSocket;

    /**
     * Constructor create TCPServer instance and set ServerSocket on the specified port.
     *
     * @param server
     * @param port
     */
    public TCPServer(int port) {
        this.port = port;
        init();
    }

    private void init() {
        try {
            this.serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            print(ERROR_SERVER_SOCKET_CREATION + port);
            print(e.getMessage());
            close();
        }
    }

    @Override
    public void run() {
        keepGoing = true;
        while (keepGoing) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();
            } catch (IOException e) {
                print(ERROR_CANT_ACCEPT_CONNECTON + socket);
                print(e.getMessage());
                close();
            }

            if (!keepGoing) {
                break;
            }

            // Create new thread on each connected client
            createClient(socket);
        }

        close();
    }

    private void createClient(Socket socket) {
        TCPClient client = new TCPClient(socket, ServerImpl.getInstance());
        client.start();
    }

    private void close() {
        keepGoing = false;
        try {
            serverSocket.close();
        } catch (IOException e) {
            print(ERROR_CLOSING_SERVER);
            print(e.getMessage());
        } finally {
            print(MESSAGE_SHUTDOWN_SERVER);
        }
    }

    private void print(String message){
    	tcpLogger.info(message);
    }

    public static void main(String[] args) {
        TCPServer tcpServer = new TCPServer(DEFAULT_PORT);
        (new Thread(tcpServer)).start();
    }

}
